package handler

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"time"
	// "github.com/spf13/viper"
)

type Handler struct {
	config *Config

	server *http.Server

	handlers  map[string]HandlerFunc
	handlerSs map[string]HandlerStuct
}

func NewHandler() (*Handler, error) {

	configFile := DEFAULT_CONFIG_FILE
	args := os.Args
	if len(args) == 2 {
		configFile = args[1]
	}
	fmt.Printf("从 %s 中获取配置文件\n", configFile)

	config, err := LoadConfig(configFile)
	if err != nil {
		return nil, err
	}

	handler := &Handler{
		config:    config,
		handlerSs: make(map[string]HandlerStuct, 10),
	}

	return handler, nil

}

type Context struct {
	R *http.Request
	W http.ResponseWriter
}

type Respone struct{}

type HandlerFunc func(c *Context) *Respone

type HandlerStuct interface {
	HandlerFunc(c *Context) *Respone
	Helper() string
}

func (handler *Handler) AddHandler(hs map[string]HandlerFunc) {
	if handler.handlers == nil {
		handler.handlers = hs
	} else {
		for r, h := range hs {
			handler.handlers[r] = h
		}
	}
}

func (handler *Handler) AddHandlerS(hs map[string]HandlerStuct) {
	for r, h := range hs {
		handler.handlerSs[r] = h
	}
}
func (handler *Handler) AddOneHandlerS(r string, h HandlerStuct) {
	handler.handlerSs[r] = h
}

func (handler *Handler) Run() error {
	s := &http.Server{
		Addr:         fmt.Sprintf(":%d", handler.config.Port),
		ReadTimeout:  time.Second * time.Duration(handler.config.ReadTimeout),
		WriteTimeout: time.Second * time.Duration(handler.config.WriteTimeout),
	}

	handler.handlerSs["/help"] = handler
	handler.registHandleFunc()

	handler.server = s

	fmt.Println("启动服务器,监听:", s.Addr)

	return s.ListenAndServe()
}

func (handler *Handler) registHandleFunc() {
	for r, h := range handler.handlers {
		http.HandleFunc(r, coverToHttpHandleFunc(h))
	}
	for r, h := range handler.handlerSs {
		http.HandleFunc(r, coverToHttpHandleFunc(h.HandlerFunc))
	}
}

func coverToHttpHandleFunc(h HandlerFunc) http.HandlerFunc {

	return func(w http.ResponseWriter, r *http.Request) {
		c := &Context{
			R: r,
			W: w,
		}
		resp := h(c)
		if resp == nil {
			return
		} else {
			buf, err := json.Marshal(resp)
			if err != nil {
				fmt.Println(err)
				return
			}
			w.Write(buf)
		}
	}
}

func (handler *Handler) Stop() error {
	if handler.server == nil {
		return nil
	}
	return handler.server.Shutdown(context.TODO())
}
